#include <buola/chart/cchart.h>

#include <buola/algorithm/container.h>
#include <buola/image/cfont.h>
#include <buola/gui/cmenu.h>
#include <buola/image/cgc.h>

namespace buola { namespace chart {

CChart::CChart()
    :   mStyle(BOX|CENTER),
        mFrameColor(std::wstring(L"lightgrey")),
        mFont(img::CFont::GetStock(L"title"))
{
    SetTitle(L"chart");
    SetBackColor(img::CColor(L"white"));

    Resize(CSize_d(400,300));

    SetWindowActions(gui::EWindowActions::DOCK|gui::EWindowActions::CLOSE|gui::EWindowActions::MINIMIZE);
}

CChart::~CChart()
{
}

void CChart::SetFrameColor(const img::CColor &pColor)
{
    mFrameColor=pColor;
    Refresh();
}

void CChart::ToggleLegend()
{
    if(Style(LEGEND))
        SetStyle(Style()&~LEGEND);
    else
        SetStyle(Style()|LEGEND);
}

void CChart::FillMenu(gui::PMenu pMenu)
{
#if 0
    if(!mMenu)
    {
        mMenu=new gui::CMenu;
        mMenu->Add(gui::new_menu_item(L"clear","edit-delete"))->eTriggered.Connect(&CChartBox::OnDelete,this);
        mMenu->AddSeparator();
        mZoomMenuItem=mMenu->Add(gui::new_checkable_menu_item(L"zoom","stock_zoom"));
        mZoomMenuItem->eTriggered.Connect(&CChartBox::OnZoom,this);
        mMenu->Add(gui::new_menu_item(L"original","stock_zoom-1"))->eTriggered.Connect(&CChartBox::OnZoomOriginal,this);
        mMenu->Add(gui::new_menu_item(L"legend","stock_chart-toggle-legend"))->eTriggered.Connect(&CChartBox::OnLegend,this);
        mMenu->AddSeparator();
        mMenu->Add(gui::new_menu_item(L"export","stock_save"))->eTriggered.Connect(&CChartBox::OnExport,this);
        mMenu->Add(gui::new_menu_item(L"print","stock_print"))->eTriggered.Connect(&CChartBox::OnPrint,this);
    }

    pMenu->AddInlineMenu(mMenu);
#endif
}

#if 0
void CChart::OnButtonDown(gui::CMouseEvent *pE)
{
    if(!mChart) return;

    if(pE->mButton==gui::EMouseButton::LEFT)
    {
        mPressed=true;

        if(mZoom.mActive)
        {
            mZoom.mChart=mChart->GetChartAt(pE->mPoint,CChart::ACTION_ZOOM);

            if(mZoom.mChart)
            {
                mZoom.mStart=pE->mPoint;
                mZoom.mCurrent=pE->mPoint;
            }
            else
            {
                mZoom.mActive=false;
                mZoomMenuItem->Check(false);
            }
        }
        else
        {
            if(mChart->OnMouseMove(pE->mPoint))
                Refresh();
        }
    }
}

void CChart::OnButtonUp(gui::CMouseEvent *pE)
{
    if(pE->mButton==gui::EMouseButton::LEFT)
    {
        if(mZoom.mActive&&mPressed)
        {
            mZoom.mCurrent=pE->mPoint;
            CRect_d lRect(mZoom.mStart,mZoom.mCurrent);
            lRect.Normalize();

            mZoom.mChart->Zoom(lRect);

            mZoom.mActive=false;
            if(mZoom.mOverlay)
            {
                mZoom.mOverlay=nullptr;
            }
            mZoomMenuItem->Check(false);

            Refresh();
        }
        else
        {
            if(mChart->OnMouseMove(pE->mPoint))
                Refresh();
        }
        mPressed=false;
    }
}

void CChart::OnMouseMove(gui::CMouseEvent *pE)
{
    if(!mChart) return;

    if(mPressed)
    {
        if(mChart->OnMouseMove(pE->mPoint))
            Refresh();
    }

    if(mZoom.mActive&&mPressed)
    {
        mZoom.mCurrent=pE->mPoint;

        CRect_d lRect(mZoom.mStart,mZoom.mCurrent);
        lRect.Normalize();
        mZoom.mChart->FixZoomRect(lRect);

        if(!mZoom.mOverlay)
        {
//          mZoom.mOverlay=new CWindow;
//            mZoom.mOverlay->Create(this,lRect);
//            mZoom.mOverlay->SetBackColor(RGBA(30,30,30,100));
//          mZoom.mOverlay->Show();
        }
        else
        {
//          mZoom.mOverlay->MoveResize(lRect);
        }

        Refresh(REFRESH_DONTEXPOSE);
    }
    else
    {
        PChart lChart=mChart->GetChartAt(pE->mPoint,CChart::ACTION_HOVER);

        if(!lChart&&!mHover.mChart) return;

        if(!lChart)
        {
            if(mHover.mOverlay)
            {
                mHover.mOverlay=nullptr;
            }
            mHover.mChart=nullptr;
            return;
        }

        if(!mHover.mOverlay)
        {
            mHover.mOverlay=new CChartOverlay(this);
            mHover.mOverlay->Create(this,mRect);
            mHover.mOverlay->Show();
        }
        else
        {
            mHover.mOverlay->Refresh();
        }

        mHover.mChart=lChart;
        mHover.mPoint=pE->mPoint;
    }
}
#endif

#if 0
void CChart::OnExport()
{
    CFileDialog lDialog;
    lDialog.Create(nullptr);
    lDialog.StayOnTopOf(this);
    lDialog.DoModal();

    if(lDialog.mResult==DIALOG_OK)
    {
        std::string lExtension=lDialog.mFile.GetExtension();
        if(lExtension=="pdf")
        {
            CPDFDoc lPDFDoc;
            lPDFDoc.Create();
            lPDFDoc.SetSize(mRect.Size());

            CGC *lGC=lPDFDoc.GetGC();
            mChart->Draw(lGC,CRect_d(CPoint_d(0,0),mRect.Size()));
            lGC->FlushPage();
            delete lGC;

            lPDFDoc.Save(lDialog.mFile);
        }
        else if(lExtension=="png")
        {
            CCairoPixmap *lPixmap=new CCairoPixmap(mRect.Size());
            CGC *lGC=lPixmap->GetGC(GC_VECTOR);
            lGC->SetSourceColor(CColor(L"lightgrey"));
            lGC->PaintClipRegion();
            mChart->Draw(lPixmap->GetGC(GC_VECTOR),
                        CRect_d(CPoint_d(0,0),mRect.Size()));
            lPixmap->WriteToPNG(lDialog.mFile);
            delete lPixmap;
        }
        else
        {
            CMessageBox::NewBox(this,L"error",L"extension "+
                    utf32(lExtension)+
                    L" unknown",MBS_OK);
        }
    }
}
#endif

#if 0
void CChartBox::OnZoom()
{
    mZoom.mActive=true;
    mPressed=false;
}

void CChartBox::OnZoomOriginal()
{
    mChart->ZoomAll();
    Refresh();
}

void CChartBox::OnLegend()
{
    mChart->ToggleLegend();
    Refresh();
}
#endif

#if 0
void CChartBox::OnPrint()
{
    CPrinter *lPrinter=CPrinter::AskPrinter();
    if(lPrinter)
    {
        lPrinter->What();

        CPrintJob *lJob=lPrinter->NewJob();
        CGC *lGC=lJob->GetGC();
        CRect_d lRect(lJob->GetMargins());
        if(lRect.w()/lRect.h()>mRect.w()/mRect.h()) //wider than window
        {
            double lW=lRect.h()*mRect.w()/mRect.h();
            double lC=(lRect.l+lRect.r)/2;
            lRect.l=lC-lW/2;
            lRect.r=lC+lW/2;
        }
        else
        {
            double lH=lRect.w()*mRect.h()/mRect.w();
            double lC=(lRect.t+lRect.b)/2;
            lRect.t=lC-lH/2;
            lRect.b=lC+lH/2;
        }
        mChart->Draw(lGC,lRect);
        lGC->FlushPage();
        delete lGC;
        lJob->Print();
    }
}
#endif

/*namespace chart*/ } /*namespace buola*/ }